package com.sztu.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.sztu.mapper.ShiroRoleMapper;
import com.sztu.mapper.ShiroRoleResourceMapper;
import com.sztu.mapper.ShiroUserMapper;
import com.sztu.mapper.ShiroUserRoleMapper;
import com.sztu.pojo.ShiroUser;
import com.sztu.pojo.ShiroUserRole;
import com.sztu.utils.DigestsUtil;
import com.sztu.utils.LongUtil;
import com.sztu.utils.RedisUtil;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

@Service
public class ShiroUserServiceImpl implements ShiroUserService{
    private final ShiroUserMapper shiroUserMapper;

    private final ShiroUserRoleMapper shiroUserRoleMapper;

    private final ShiroRoleResourceMapper shiroRoleResourceMapper;

    private final RedisUtil shiroRedisUtil;

    private final ShiroRoleMapper shiroRoleMapper;

    //三天
    private final Long TimeOut=60*60*24*3L;

    public ShiroUserServiceImpl(ShiroUserMapper shiroUserMapper, ShiroUserRoleMapper shiroUserRoleMapper, ShiroRoleResourceMapper shiroRoleResourceMapper, RedisUtil shiroRedisUtil, ShiroRoleMapper shiroRoleMapper) {
        this.shiroUserMapper = shiroUserMapper;
        this.shiroUserRoleMapper = shiroUserRoleMapper;
        this.shiroRoleResourceMapper = shiroRoleResourceMapper;
        this.shiroRedisUtil = shiroRedisUtil;
        this.shiroRoleMapper = shiroRoleMapper;
    }

    @Override
    public ShiroUser getPwdByAccount(String account) {
        ShiroUser shiroUser=new ShiroUser();
        Map map=null;
        if(map!=null&&map.getOrDefault("password",null)!=null&&map.getOrDefault("salt",null)!=null){
            shiroUser.setPassword((String) map.get("password"));
            shiroUser.setSalt((String) map.get("salt"));
        }
        else {
            if(map==null)map=new HashMap();
            QueryWrapper<ShiroUser> queryWrapper=new QueryWrapper();
            queryWrapper.select("password","salt","id");
            queryWrapper.eq("account",account);
            shiroUser=shiroUserMapper.selectOne(queryWrapper);
            map.put("password",shiroUser.getPassword());
            map.put("salt",shiroUser.getSalt());
            shiroRedisUtil.hmset(account,map,TimeOut);
        }
        return shiroUser;
    }

    @Override
    public List<String> getRolesById(Long id) {
        return shiroUserRoleMapper.getRolesByUserId(id);
    }

    @Override
    public List<String> getResSourceByRoles(List<String> roles) {
        List<String> resource=new ArrayList<>();
        for(String role : roles){
            List tempResource=shiroRoleResourceMapper.getListByRoleLabel(role);
            resource.addAll((Collection<String>) tempResource.parallelStream().filter(Objects::nonNull).collect(Collectors.toList()));
        }
        return resource;
    }

    @Override
    public Map<String, List> getRolesAndResByAccount(String account) {
        Map map=shiroRedisUtil.hmget(account);
        if(map==null||map.getOrDefault("roles",null)==null||map.getOrDefault("resource",null)==null){
            if(map==null) map=new HashMap();
            QueryWrapper<ShiroUser> queryWrapper=new QueryWrapper();
            queryWrapper.eq("account",account);
            queryWrapper.select("id");
            ShiroUser user=shiroUserMapper.selectOne(queryWrapper);

            List roles=getRolesById(user.getId());
            List resource=getResSourceByRoles(roles);

            map.put("roles",roles);
            map.put("resource",resource);

            shiroRedisUtil.hmset(account,map,TimeOut);
        }

        return map;
    }

    @Override
    public String getShiroNameById(Long id) {
        QueryWrapper<ShiroUser> queryWrapper=new QueryWrapper();
        queryWrapper.eq("id",id);
        queryWrapper.select("name");
        return shiroUserMapper.selectOne(queryWrapper).getName();
    }

    @Override
    public List<Map<String, Object>> getPrincipalUsers() {
        return shiroUserMapper.selectUserByRoleName("房间负责人");
    }

    @Override
    public List<Map<String, Object>> getAllShiroUser() {
        return shiroUserMapper.selectMaps(null);
    }

    @Override
    public void addShiroUserByMap(Map<String, Object> map) {
        map.put("college_id",1L);
        map.put("account",UUID.randomUUID().toString());
        shiroUserMapper.insertSimpleShiroUser(map);
        addDefaultPermission(LongUtil.parseLong(map.get("id")));
        map.put("password","123456");
        setPassword(map);
    }

    @Override
    public void updateShiroUserByMap(Map<String,Object> map) {
        shiroUserMapper.updateById(generateUserByMap(map));
    }

    @Override
    public void deleteShiroUserList(List<String> idList) {
        List<Long> longIdList=idList.stream().map(s -> {
            return Long.parseLong(s);
        }).collect(Collectors.toList());
        shiroUserMapper.deleteBatchIds(longIdList);
    }

    @Override
    public List<Map<String, Object>> getAllPermissionOfUser() {
        return shiroUserRoleMapper.selectAllByMaps();
    }

    @Override
    public void deleteUserPermission(Map<String, Object> map) {

    }

    @Override
    public void updateUserPermission(Map<String, Object> map) {
        ShiroUserRole shiroUserRole=new ShiroUserRole()
                                    .setRoleId(LongUtil.parseLong(map.getOrDefault("role_id",null)))
                                    .setId(LongUtil.parseLong(map.getOrDefault("id",null)))
                                    .setUserId(LongUtil.parseLong(map.getOrDefault("user_id",null)));
        shiroUserRoleMapper.updateById(shiroUserRole);
    }

    @Override
    public void addDefaultPermission(Long id) {
        shiroUserRoleMapper.insert(new ShiroUserRole().setUserId(id).setRoleId(2L));
    }

    @Override
    public List<Map<String, Object>> getAllRoleList() {
        return shiroRoleMapper.selectMaps(null);
    }

    @Override
    public void setPassword(Map<String, Object> userInfo) {
        String password= (String) userInfo.getOrDefault("password",null);
        userInfo.putAll(DigestsUtil.entryPassword(password));
        ShiroUser user=new ShiroUser()
                .setId(LongUtil.parseLong(userInfo.getOrDefault("id",null)))
                .setPassword((String) userInfo.getOrDefault("password",null))
                .setSalt((String) userInfo.getOrDefault("salt",null))
                ;
        shiroUserMapper.updateById(user);
    }

    private ShiroUser generateUserByMap(Map<String,Object> map){
        return new ShiroUser()
                .setName((String) map.getOrDefault("name",null))
                .setAccount((String) map.getOrDefault("account",null))
                .setCollegeId(LongUtil.parseLong(map.getOrDefault("college_id",null)))
                .setId(LongUtil.parseLong(map.getOrDefault("id",null)))
                ;
    }
}
